home *** CD-ROM | disk | FTP | other *** search
- /*
- File: QTSound.c
-
- Contains: Sound code for QuickTime CreateMovie sample
-
- Written by: Scott Kuechle
- (based heavily on QuickTime sample code in Inside Macintosh: QuickTime)
-
- Copyright: © 1998 by Apple Computer, Inc. All rights reserved
-
- Change History (most recent first)
-
- <2> 9/28/98 rtm changes for Metrowerks compiler
- <1> 6/26/98 srk first file
-
-
- */
-
- /************************************************************
- * *
- * INCLUDE FILES *
- * *
- *************************************************************/
-
-
- #if !defined(_MSC_VER) && _WIN32
- #include <Win32Headers.mch>
- #define TARGET_OS_WIN32 1
- #else
- #include <ConditionalMacros.h>
- #endif
-
- #if TARGET_OS_WIN32
- #include <QTML.h>
- #define STRICT
- #include <windows.h>
- #endif
-
- #include <Resources.h>
- #include <FixMath.h>
- #include <Sound.h>
-
- #include "CreateMovie.h"
- #include "QTSound.h"
-
- /************************************************************
- * *
- * TYPE DEFINITIONS *
- * *
- *************************************************************/
-
- typedef SndCommand *SndCmdPtr;
-
- #if PRAGMA_STRUCT_ALIGN
- #pragma options align=mac68k
- #elif PRAGMA_STRUCT_PACKPUSH
- #pragma pack(push, 2)
- #elif PRAGMA_STRUCT_PACK
- #pragma pack(2)
- #endif
-
- /* 'snd ' resource format 1 - see the Sound Manager chapter of Inside Macintosh: Sound
- for the details */
- typedef struct
- {
- short format;
- short numSynths;
- } Snd1Header, *Snd1HdrPtr, **Snd1HdrHndl;
-
- /* 'snd ' resource format 2 - see the Sound Manager chapter of Inside Macintosh: Sound
- for the details */
-
- typedef struct
- {
- short format;
- short refCount;
- } Snd2Header, *Snd2HdrPtr, **Snd2HdrHndl;
-
-
- #if PRAGMA_STRUCT_ALIGN
- #pragma options align=reset
- #elif PRAGMA_STRUCT_PACKPUSH
- #pragma pack(pop)
- #elif PRAGMA_STRUCT_PACK
- #pragma pack()
- #endif
-
- /************************************************************
- * *
- * FUNCTION PROTOTYPES *
- * *
- *************************************************************/
-
- static void QTSound_CreateSoundDescription (Handle sndHandle,
- SoundDescriptionHandle sndDesc,
- long *sndDataOffset,
- long *numSamples,
- long *sndDataSize );
- static long QTSound_GetSndHdrOffset (Handle sndHandle);
-
- /************************************************************
- * *
- * CONSTANTS *
- * *
- *************************************************************/
-
- #define kOurSoundResourceID 128
-
- #define kSoundSampleDuration 1
- #define kSyncSample 0
- #define kTrackStart 0
- #define kMediaStart 0
- /*
- for the following constants, please consult the Macintosh
- Audio Compression and Expansion Toolkit
- */
- #define kMACEBeginningNumberOfBytes 6
- #define kMACE31MonoPacketSize 2
- #define kMACE31StereoPacketSize 4
- #define kMACE61MonoPacketSize 1
- #define kMACE61StereoPacketSize 2
-
-
- /************************************************************
- * *
- * QTSound_CreateMySoundTrack() *
- * *
- * Creates a QuickTime movie sound track & media data *
- * *
- *************************************************************/
-
-
- void QTSound_CreateMySoundTrack (Movie theMovie)
- {
- Track theTrack;
- Media theMedia;
- Handle sndHandle = nil;
- SoundDescriptionHandle sndDesc = nil;
- long sndDataOffset;
- long sndDataSize;
- long numSamples;
- OSErr err = noErr;
- #if TARGET_OS_WIN32
-
- char path[MAX_PATH+1];
- short resID;
- FSSpec fsspec;
-
-
- fsspec.vRefNum = 0;
- fsspec.parID = 0;
- GetModuleFileName( NULL, path, MAX_PATH+1);
-
- NativePathNameToFSSpec((char *)&path, &fsspec, 0);
-
- /* open our application resource file so we
- can access the Macintosh 'snd ' resource */
- resID = FSpOpenResFile(&fsspec, fsRdPerm);
- CheckError (ResError(), "FSpOpenResFile error" );
-
- #endif
-
-
-
- sndHandle = GetResource ('snd ', kOurSoundResourceID);
- CheckError (ResError(), "GetResource error" );
- if (sndHandle == nil)
- {
- return;
- }
-
- sndDesc = (SoundDescriptionHandle) NewHandle(4);
- CheckError (MemError(), "NewHandle error" );
-
- QTSound_CreateSoundDescription (sndHandle,
- sndDesc,
- &sndDataOffset,
- &numSamples,
- &sndDataSize );
-
- theTrack = NewMovieTrack (theMovie, 0, 0, kFullVolume);
- CheckError (GetMoviesError(), "NewMovieTrack error" );
-
- theMedia = NewTrackMedia (theTrack, SoundMediaType,
- FixRound ((**sndDesc).sampleRate),
- nil, 0);
- CheckError (GetMoviesError(), "NewTrackMedia error" );
-
- err = BeginMediaEdits (theMedia);
- CheckError( err, "BeginMediaEdits error" );
-
- err = AddMediaSample(theMedia,
- sndHandle,
- sndDataOffset,/* offset in data */
- sndDataSize,
- kSoundSampleDuration,/* duration of each sound sample */
- (SampleDescriptionHandle) sndDesc,
- numSamples,
- kSyncSample,/* self-contained samples */
- nil);
- CheckError( err, "AddMediaSample error" );
-
- err = EndMediaEdits (theMedia);
- CheckError( err, "EndMediaEdits error" );
-
- err = InsertMediaIntoTrack (theTrack,
- kTrackStart,/* track start time */
- kMediaStart,/* media start time */
- GetMediaDuration (theMedia),
- fixed1);
- CheckError( err, "InsertMediaIntoTrack error" );
-
- if (sndDesc != nil)
- {
- DisposeHandle( (Handle)sndDesc);
- }
- }
-
- /************************************************************
- * *
- * QTSound_CreateSoundDescription() *
- * *
- * Creates a SoundDescription structure for a given sound *
- * sample *
- * *
- *************************************************************/
-
- static void QTSound_CreateSoundDescription (Handle sndHandle,
- SoundDescriptionHandle sndDesc,
- long *sndDataOffset,
- long *numSamples,
- long *sndDataSize )
- {
- long sndHdrOffset = 0;
- long sampleDataOffset;
- SoundHeaderPtr sndHdrPtr = nil;
- long numFrames;
- long samplesPerFrame;
- long bytesPerFrame;
- SoundDescriptionPtr sndDescPtr;
-
-
- *sndDataOffset = 0;
- *numSamples = 0;
- *sndDataSize = 0;
-
- SetHandleSize( (Handle)sndDesc, sizeof(SoundDescription) );
- CheckError(MemError(),"SetHandleSize error");
- sndHdrOffset = QTSound_GetSndHdrOffset (sndHandle);
- if (sndHdrOffset == 0)
- {
- CheckError(-1, "QTSound_GetSndHdrOffset error");
- }
-
- /* we can use pointers since we don't move memory */
- sndHdrPtr = (SoundHeaderPtr) (*sndHandle + sndHdrOffset);
- sndDescPtr = *sndDesc;
-
- sndDescPtr->descSize = sizeof (SoundDescription);
- /* total size of sound description structure */
- sndDescPtr->resvd1 = 0;
- sndDescPtr->resvd2 = 0;
- sndDescPtr->dataRefIndex = 1;
- sndDescPtr->compressionID = 0;
- sndDescPtr->packetSize = 0;
- sndDescPtr->version = 0;
- sndDescPtr->revlevel = 0;
- sndDescPtr->vendor = 0;
-
- switch (sndHdrPtr->encode)
- {
- case stdSH:
- sndDescPtr->dataFormat = kRawCodecType;
- /* uncompressed offset-binary data */
- sndDescPtr->numChannels = 1;
- /* number of channels of sound */
- sndDescPtr->sampleSize = 8;
- /* number of bits per sample */
- sndDescPtr->sampleRate = sndHdrPtr->sampleRate;
- /* sample rate */
- *numSamples = sndHdrPtr->length;
- *sndDataSize = *numSamples;
- bytesPerFrame = 1;
- samplesPerFrame = 1;
- sampleDataOffset = (Ptr)&sndHdrPtr->sampleArea - (Ptr)sndHdrPtr;
- break;
-
- case extSH:
- {
- ExtSoundHeaderPtr extSndHdrP;
-
- extSndHdrP = (ExtSoundHeaderPtr)sndHdrPtr;
- sndDescPtr->dataFormat = kRawCodecType;
- /* uncompressed offset-binary data */
-
- /* we typecast a long to a short here, and it should really be fixed */
- sndDescPtr->numChannels = (short)extSndHdrP->numChannels;
- /* number of channels of sound */
- sndDescPtr->sampleSize = extSndHdrP->sampleSize;
- /* number of bits per sample */
- sndDescPtr->sampleRate = extSndHdrP->sampleRate;
- /* sample rate */
- numFrames = extSndHdrP->numFrames;
- *numSamples = numFrames;
- bytesPerFrame = extSndHdrP->numChannels * ( extSndHdrP->sampleSize / 8);
- samplesPerFrame = 1;
- *sndDataSize = numFrames * bytesPerFrame;
- sampleDataOffset = (Ptr)(&extSndHdrP->sampleArea) - (Ptr)extSndHdrP;
- }
- break;
-
- case cmpSH:
- {
- CmpSoundHeaderPtr cmpSndHdrP;
-
- cmpSndHdrP = (CmpSoundHeaderPtr)sndHdrPtr;
- /* we typecast a long to a short here, and it should really be fixed */
-
- sndDescPtr->numChannels = (short)cmpSndHdrP->numChannels;
- /* number of channels of sound */
- sndDescPtr->sampleSize = cmpSndHdrP->sampleSize;
- /* number of bits per sample before compression */
- sndDescPtr->sampleRate = cmpSndHdrP->sampleRate;
- /* sample rate */
- numFrames = cmpSndHdrP->numFrames;
- sampleDataOffset =(Ptr)(&cmpSndHdrP->sampleArea) - (Ptr)cmpSndHdrP;
-
- switch (cmpSndHdrP->compressionID)
- {
- case threeToOne:
- sndDescPtr->dataFormat = kMACE3Compression;
- /* compressed 3:1 data */
- samplesPerFrame = kMACEBeginningNumberOfBytes;
- *numSamples = numFrames * samplesPerFrame;
-
- switch (cmpSndHdrP->numChannels)
- {
- case 1:
- bytesPerFrame = cmpSndHdrP->numChannels
- * kMACE31MonoPacketSize;
- break;
-
- case 2:
- bytesPerFrame = cmpSndHdrP->numChannels
- * kMACE31StereoPacketSize;
- break;
-
- default:
- CheckError(-1, "Corrupt sound data" );
- break;
- }
-
- *sndDataSize = numFrames * bytesPerFrame;
- break;
-
- case sixToOne:
- sndDescPtr->dataFormat = kMACE6Compression;
- /* compressed 6:1 data */
- samplesPerFrame = kMACEBeginningNumberOfBytes;
- *numSamples = numFrames * samplesPerFrame;
-
- switch (cmpSndHdrP->numChannels)
- {
- case 1:
- bytesPerFrame = cmpSndHdrP->numChannels
- * kMACE61MonoPacketSize;
- break;
-
- case 2:
- bytesPerFrame = cmpSndHdrP->numChannels
- * kMACE61StereoPacketSize;
- break;
-
- default:
- CheckError(-1, "Corrupt sound data" );
- break;
- }
-
- *sndDataSize = (*numSamples) * bytesPerFrame;
- break;
-
- default:
- CheckError(-1, "Corrupt sound data" );
- break;
- }
-
- } /* switch cmpSndHdrP->compressionID:*/
-
- break; /* of cmpSH: */
-
- default:
- CheckError(-1, "Corrupt sound data" );
- break;
-
- } /* switch sndHdrPtr->encode */
-
- *sndDataOffset = sndHdrOffset + sampleDataOffset;
- }
-
-
- /************************************************************
- * *
- * QTSound_GetSndHdrOffset() *
- * *
- * Returns an pointer to the first sound command in the *
- * sound resource *
- * *
- *************************************************************/
-
- static long QTSound_GetSndHdrOffset (Handle sndHandle)
- {
- short howManyCmds;
- long sndOffset = 0;
- Ptr sndPtr;
-
- if (sndHandle == nil)
- {
- return 0;
- }
- sndPtr = *sndHandle;
- if (sndPtr == nil)
- {
- return 0;
- }
-
- if ((*(SndListPtr)sndPtr).format == firstSoundFormat)
- {
- short synths = ((SndListPtr)sndPtr)->numModifiers;
- sndPtr += ( sizeof(Snd1Header) + (sizeof(ModRef) * synths) );
- }
- else
- {
- sndPtr += sizeof(Snd2Header);
- }
-
- howManyCmds = *(short *)sndPtr;
-
- sndPtr += sizeof(howManyCmds);
- /*
- sndPtr is now at the first sound command--cruise all
- commands and find the first soundCmd or bufferCmd
- */
- while (howManyCmds > 0)
- {
- switch (((SndCmdPtr)sndPtr)->cmd)
- {
- case (soundCmd + dataOffsetFlag):
- case (bufferCmd + dataOffsetFlag):
- sndOffset = ((SndCmdPtr)sndPtr)->param2;
- howManyCmds = 0; /* done, get out of loop */
- break;
-
- default:/* catch any other type of commands */
- sndPtr += sizeof(SndCommand);
- howManyCmds--;
- break;
- }
- }/* done with all commands */
-
- return sndOffset;
- }/* of GetSndHdrOffset */
-